﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows;

namespace Yang
{

    public static class WindowAPI
    {
        public static event Action<string>? OnLog;

        [StructLayout(LayoutKind.Sequential)]  
        public struct RECT    {  
            public int left;  
            public int top;  
            public int right;  
            public int bottom;  
        }

        [Flags]
        public enum MouseEventFlag : uint //设置鼠标动作的键值
        {
            Move = 0x0001,               //发生移动
            LeftDown = 0x0002,           //鼠标按下左键
            LeftUp = 0x0004,             //鼠标松开左键
            RightDown = 0x0008,          //鼠标按下右键
            RightUp = 0x0010,            //鼠标松开右键
            MiddleDown = 0x0020,         //鼠标按下中键
            MiddleUp = 0x0040,           //鼠标松开中键
            XDown = 0x0080,
            XUp = 0x0100,
            Wheel = 0x0800,              //鼠标轮被移动
            VirtualDesk = 0x4000,        //虚拟桌面
            Absolute = 0x8000
        }
        private const int KBC_KEY_CMD = 0x64;
        private const int KBC_KEY_DATA = 0x60;
        [DllImport("winio64.dll")]
        public static extern bool InitializeWinIo();
        [DllImport("winio64.dll")]
        private static extern bool GetPortVal(IntPtr wPortAddr, out int pdwPortVal, byte bSize);
        [DllImport("winio64.dll")]
        private static extern bool SetPortVal(uint wPortAddr, IntPtr dwPortVal, byte bSize);
        [DllImport("winio64.dll")]
        private static extern byte MapPhysToLin(byte pbPhysAddr, uint dwPhysSize, IntPtr PhysicalMemoryHandle);
        [DllImport("winio64.dll")]
        private static extern bool UnmapPhysicalMemory(IntPtr PhysicalMemoryHandle, byte pbLinAddr);
        [DllImport("winio64.dll")]
        private static extern bool GetPhysLong(IntPtr pbPhysAddr, byte pdwPhysVal);
        [DllImport("winio64.dll")]
        private static extern bool SetPhysLong(IntPtr pbPhysAddr, byte dwPhysVal);
        [DllImport("winio64.dll")]
        public static extern void ShutdownWinIo();
        [DllImport("user32.dll")]
        private static extern int MapVirtualKey(uint Ucode, uint uMapType);
        [DllImport("user32.dll")]
        public static extern IntPtr GetWindowDC(IntPtr hwnd);

        [DllImport("user32.dll")] 
        public static extern IntPtr GetWindowRect(IntPtr hWnd, ref RECT rect);
 
        [DllImport("Gdi32.dll")]
        public static extern uint GetPixel(IntPtr hdc, int nXPos, int nYPos);

        [DllImport("user32.dll", EntryPoint = "FindWindow", CharSet = CharSet.Auto)]
        public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

        [DllImport("gdi32.dll")]
        public static extern IntPtr CreateSolidBrush(int crColor);

        [DllImport("gdi32.dll")]
        public static extern bool Rectangle(IntPtr hdc, int X1, int Y1, int X2, int Y2);

        [DllImport("gdi32.dll")]
        public static extern IntPtr CreatePen(int nPenStyle, int nWidth, int crColor);

        [DllImport("gdi32.dll")]
        public static extern IntPtr DeleteObject(IntPtr hObject);

        [DllImport("gdi32.dll")]
        public static extern IntPtr SelectObject(IntPtr hdc, IntPtr pen);

        [DllImport("gdi32.dll")]
        public static extern bool BitBlt(IntPtr hdcDest, int xDest, int yDest, int wDest, int hDest, IntPtr hdcSource, int xSrc, int ySrc, int RasterOp);

        [DllImport("gdi32.dll")]
        public static extern IntPtr CreateCompatibleBitmap(IntPtr hdc, int nWidth, int nHeight);

        [DllImport("gdi32.dll")]
        public static extern IntPtr CreateCompatibleDC(IntPtr hdc);
        [DllImport("gdi32.dll")]
        public static extern bool DeleteDC(IntPtr hDC);

        [DllImport("user32.dll")]
        public static extern bool SetCursorPos(int X, int Y);

        //设置鼠标按键和动作
        [DllImport("user32.dll")]
        public static extern void mouse_event(MouseEventFlag flags, int dx, int dy, uint data, UIntPtr extraInfo);

        //方法：鼠标左键单击操作：鼠标左键按下和松开两个事件的组合即一次单击
        public static void MouseLeftClickEvent(int dx, int dy, uint data)
        {
            SetCursorPos(dx, dy);
            System.Threading.Thread.Sleep(500);
            mouse_event(MouseEventFlag.LeftDown , dx, dy, data, UIntPtr.Zero);
            System.Threading.Thread.Sleep(1);
            mouse_event(MouseEventFlag.LeftUp, dx, dy, data, UIntPtr.Zero);
        }
        ///等待键盘缓冲区为空
        private static void KBCWait4IBE()
        {
            int dwVal = 0;
            //do
            //{
            //    bool flag = MyGetPortl((IntPtr)0x64, out dwVal, 1);
            //}
            //while ((dwVal & 0x2) > 0);
        }

        public static bool MySetPort(uint addr,IntPtr port,byte value)
        {
            var rv = SetPortVal(addr, port, value);
            OnLog?.Invoke($"SetPort:{rv},addr:{addr},port:{port},byte:{value}");
            return rv;
        }

        public static bool MyGetPortl(IntPtr addr, out int value, byte size)
        {
            var rv = GetPortVal(addr, out value, size);
            OnLog?.Invoke($"GetPort:{rv},addr:{addr},value:{value},size:{size}");
            return rv;

        }

        public static bool MyMouseDown()
        {
            KBCWait4IBE();
            MySetPort(KBC_KEY_CMD, (IntPtr)0xD3, 1);
            KBCWait4IBE();
            MySetPort(KBC_KEY_DATA, (IntPtr)0x09, 1);
            KBCWait4IBE();
            MySetPort(KBC_KEY_CMD, (IntPtr)0xD3, 1);
            KBCWait4IBE();
            MySetPort(KBC_KEY_DATA, (IntPtr)0x00, 1);
            KBCWait4IBE();
            MySetPort(KBC_KEY_CMD, (IntPtr)0xD3, 1);
            KBCWait4IBE();
            MySetPort(KBC_KEY_DATA, (IntPtr)0x00, 1);
            KBCWait4IBE();
            MySetPort(KBC_KEY_CMD, (IntPtr)0xD3, 1);
            KBCWait4IBE();
            MySetPort(KBC_KEY_DATA, (IntPtr)0x00, 1);
            return true;
        }

        public static bool MyMouseDown2()
        {
            int btScancode = 0;
            btScancode = MapVirtualKey((byte)0x0002, 0);
            KBCWait4IBE();
            MySetPort(KBC_KEY_CMD, (IntPtr)0xD3, 1);
            KBCWait4IBE();
            MySetPort(KBC_KEY_DATA, (IntPtr)(btScancode | 0x80), 1);
            return true;// 'write in io
        }
        public static bool MyMouseUp2()
        {
            int btScancode = 0;
            btScancode = MapVirtualKey((byte)0x0004, 0);
            KBCWait4IBE();
            MySetPort(KBC_KEY_CMD, (IntPtr)0xD3, 1);
            KBCWait4IBE();
            MySetPort(KBC_KEY_DATA, (IntPtr)(btScancode | 0x80), 1);
            return true;// 'write in io
        }
        /// Simulate mouse up
        public static bool MyMouseUp()
        {
            KBCWait4IBE();
            MySetPort(KBC_KEY_CMD, (IntPtr)0xD3, 1);
            KBCWait4IBE();
            MySetPort(KBC_KEY_DATA, (IntPtr)0x08, 1);
            KBCWait4IBE();
            MySetPort(KBC_KEY_CMD, (IntPtr)0xD3, 1);
            KBCWait4IBE();
            MySetPort(KBC_KEY_DATA, (IntPtr)0x00, 1);
            KBCWait4IBE();
            MySetPort(KBC_KEY_CMD, (IntPtr)0xD3, 1);
            KBCWait4IBE();
            MySetPort(KBC_KEY_DATA, (IntPtr)0x00, 1);
            KBCWait4IBE();
            MySetPort(KBC_KEY_CMD, (IntPtr)0xD3, 1);
            KBCWait4IBE();
            MySetPort(KBC_KEY_DATA, (IntPtr)0x00, 1);
            return true;
        }

        public static void CutImage(this Bitmap source, Rectangle rect, string filename)
        {
            Bitmap rv = new Bitmap(rect.Width, rect.Height);
            Graphics g = Graphics.FromImage(rv);
            g.DrawImageUnscaledAndClipped(source, rect);
            g.Dispose();
            rv.Save(filename);
            rv.Dispose();
        }
    }
}
